#include "timer.h"
#include "util.h"
#include "marco.h"

//比较两个计时器
bool Timer::Comparator::operator()(const Timer::ptr& lhs ,const Timer::ptr& rhs) const {
    if(!lhs && !rhs) { return false; } //两个都为null
    if(!lhs) { return true; } //左边为null
    if(!rhs) { return false; } //右边为null
    if(lhs->m_next < rhs->m_next) { return true; } //左大
    if(rhs->m_next < lhs->m_next) { return false; } //右小
    return lhs.get() < rhs.get(); //时间一样比较地址
}

Timer::Timer(uint64_t ms, std::function<void()> cb, bool recurring, TimerManager* manager)
    :m_recurring(recurring)
    ,m_ms(ms)
    ,m_cb(cb) //定时器执行任务的回调函数
    ,m_manager(manager) {
    //m_next = sylar::GetElapsedMS() + m_ms;
    m_next = sylar::GetCurrentMS() + m_ms;
}

Timer::Timer(uint64_t next) //直接获取到时间
    :m_next(next) {
}

//取消定时器
bool Timer::cancel() {
    TimerManager::RWMutexType::writeLock lock(m_manager->m_mutex);
    if(m_cb) {
        m_cb = nullptr; //先取消回调函数
        auto it = m_manager->m_timers.find(shared_from_this()); //查到到容器中对应的定时器 
        m_manager->m_timers.erase(it); //移除定时器
        return true;
    }
    return false;
}

//重新设置定时器的执行时间
bool Timer::refresh() {
    TimerManager::RWMutexType::writeLock lock(m_manager->m_mutex);
    if(!m_cb) {
        return false;
    }
    auto it = m_manager->m_timers.find(shared_from_this());
    if(it == m_manager->m_timers.end()) { //是否是最后一个
        return false;
    }
    m_manager->m_timers.erase(it); //把原来的定时器删除
    //m_next = sylar::GetElapsedMS() + m_ms;
    m_next = sylar::GetCurrentMS() + m_ms; //重置定时器事件
    m_manager->m_timers.insert(shared_from_this()); //把重置好的对象添加到定时器容器中
    return true;
}

//重置定时器时间
bool Timer::reset(uint64_t ms, bool from_now) {
    if(ms == m_ms && !from_now) { //判断时间是否需要改变
        return true;
    }
    TimerManager::RWMutexType::writeLock lock(m_manager->m_mutex);
    if(!m_cb) {
        return false;
    }
    auto it = m_manager->m_timers.find(shared_from_this());
    if(it == m_manager->m_timers.end()) {
        return false;
    }
    m_manager->m_timers.erase(it);
    uint64_t start = 0;
    if(from_now) { //现在开始执行
        //start = sylar::GetElapsedMS();
        start = sylar::GetCurrentMS();
    } else {
        start = m_next - m_ms; //下一个定时器减去当前的时间
    }
    m_ms = ms; //修改执行时间
    m_next = start + m_ms; //修改精确的执行时间
    m_manager->addTimer(shared_from_this(), lock); //添加定时器
    return true;
}

//TimerManager部分
TimerManager::TimerManager() {
    m_previouseTime = sylar::GetCurrentMS();
}

TimerManager::~TimerManager() {
}

Timer::ptr TimerManager::addTimer(uint64_t ms, std::function<void()> cb
                                  ,bool recurring) {
    Timer::ptr timer(new Timer(ms, cb, recurring, this));
    RWMutexType::writeLock lock(m_mutex);
    addTimer(timer, lock);
    return timer;
}

//条件定时器的辅助函数 定时器被唤醒 执行该函数
static void OnTimer(std::weak_ptr<void> weak_cond, std::function<void()> cb) {
    std::shared_ptr<void> tmp = weak_cond.lock();//返回weak_cond的智能指针
    if(tmp) { //智能指针不为空
        cb(); //执行回调函数
    }
}

//添加条件定时器
Timer::ptr TimerManager::addConditionTimer(uint64_t ms, std::function<void()> cb
                                    ,std::weak_ptr<void> weak_cond
                                    ,bool recurring) {
    return addTimer(ms, std::bind(&OnTimer, weak_cond, cb), recurring); //直接绑定回调函数
}

//获取下一个定时器的执行需要等待的时间
uint64_t TimerManager::getNextTimer() {
    RWMutexType::readLock lock(m_mutex);
    m_tickled = false;
    if(m_timers.empty()) { //没有任务要执行
        return ~0ull; //返回一个最大的值
    }

    const Timer::ptr& next = *m_timers.begin(); //获取容器中的第一个定时器
    uint64_t now_ms = sylar::GetCurrentMS(); //获取当前时间
    if(now_ms >= next->m_next) { //如果当前时间大于下一个定时器，证明不明原因导致该定时器没有被唤醒
        return 0; 
    } else {
        return next->m_next - now_ms; //返回需要等待的时间
    }
}

//已经超过时间的定时器 需要返回对应的回调函数
void TimerManager::listExpiredCb(std::vector<std::function<void()> >& cbs) {
    //uint64_t now_ms = sylar::GetElapsedMS();
    uint64_t now_ms = sylar::GetCurrentMS();
    std::vector<Timer::ptr> expired; //超时的定时器
    {
        RWMutexType::readLock lock(m_mutex);
        if(m_timers.empty()) { //如果没有，直接返回
            return;
        }
    }
    RWMutexType::writeLock lock(m_mutex);
    if(m_timers.empty()) {
        return;
    }
    bool rollover = false;
    if(SYLAR_UNLIKELY(detectClockRollover(now_ms))) {
        // 使用clock_gettime(CLOCK_MONOTONIC_RAW)，应该不可能出现时间回退的问题
        rollover = true;
    }
    if(!rollover && ((*m_timers.begin())->m_next > now_ms)) { //判断没有超时 需要继续修改
        return;
    }

    Timer::ptr now_timer(new Timer(now_ms)); //创建一个定时器，使用当前时间
    auto it = rollover ? m_timers.end() : m_timers.lower_bound(now_timer);//查找第一个不小于给定值的元素
    while(it != m_timers.end() && (*it)->m_next == now_ms) {
        ++it; //跳到下一个
    }
    expired.insert(expired.begin(), m_timers.begin(), it);//把超时的定时器存放在容器
    m_timers.erase(m_timers.begin(), it);//把原来的超时定时器从容器中删除
    cbs.reserve(expired.size()); //设置长度

    for(auto& timer : expired) {
        cbs.push_back(timer->m_cb); //把回调函数添加进容器
        if(timer->m_recurring) { //判断是否是循环定时器
            timer->m_next = now_ms + timer->m_ms; //重置到下一个定时器
            m_timers.insert(timer); //添加到容器中
        } else {
            timer->m_cb = nullptr; //置空
        }
    }
}

void TimerManager::addTimer(Timer::ptr val, RWMutexType::writeLock& lock) {
    auto it = m_timers.insert(val).first;//insert插入之后会返回一个pair，第一个first表示位置
    bool at_front = (it == m_timers.begin()) && !m_tickled; //判断是否插入到容器中的第一个位置
    if(at_front) {
        m_tickled = true;
    }
    lock.unlock();

    if(at_front) {
        onTimerInsertedAtFront(); //该函数唤醒原来的定时器，重新设置一个定时时间
    }
}

//检测时间 让程序可以适应时间变动
bool TimerManager::detectClockRollover(uint64_t now_ms) {
    bool rollover = false;
    if(now_ms < m_previouseTime && //当前时间戳小于上次执行时间
            now_ms < (m_previouseTime - 60 * 60 * 1000)) { 
        rollover = true;
    }
    m_previouseTime = now_ms; //认为已经回滚  F
    return rollover;
}

//检索是否右定时器
bool TimerManager::hasTimer() {
    RWMutexType::readLock lock(m_mutex);
    return !m_timers.empty();
}


